Kubernetes Probes (Liveness, Readiness, Startup)
Kubernetesでは、コンテナの健康状態を監視し、自動的に回復やトラフィック制御を行うために Probe(プローブ) という仕組みが提供されています。適切にProbeを設定することで、アプリケーションの可用性と信頼性を大きく向上させることができます。
3種類のProbeとその役割
Kubernetesには、目的の異なる3つのProbeが存在します。これらを適切に使い分けることが重要です。
1. Liveness Probe (生存確認)
- 目的: アプリケーションが「生きているか(デッドロックや無限ループに陥っていないか)」を確認します。
- 動作: 失敗すると、kubeletはコンテナを 再起動 (Restart) します。
- ユースケース: アプリケーションがクラッシュはしていないが、内部エラーで応答不能になっている場合など、再起動によってのみ回復できる状態を検知するために使用します。
2. Readiness Probe (準備完了確認)
- 目的: アプリケーションが「トラフィックを受け入れる準備ができているか」を確認します。
- 動作: 失敗すると、そのPodのIPアドレスがServiceのロードバランシング対象(Endpoints)から 除外 されます(再起動はされません)。
- ユースケース: アプリケーションの起動処理中、大量のデータロード中、あるいは一時的な過負荷でリクエストを処理できない場合に、トラフィックが流れるのを防ぐために使用します。
3. Startup Probe (起動確認)
- 目的: アプリケーションの「起動が完了したか」を確認します。
- 動作: このProbeが成功するまで、Liveness ProbeとReadiness Probeは無効化されます。失敗し続けると(設定された回数を超えると)、コンテナは再起動されます。
- ユースケース: レガシーアプリや大規模なJavaアプリなど、起動に時間がかかるアプリケーションで使用します。Liveness Probeの
initialDelaySecondsを長く設定する代わりに使用します。
Probeのチェック方式
各Probeでは、以下の3つの方式のいずれかを使用してチェックを行います。
- HTTP GET: 指定したパスとポートにHTTP GETリクエストを送信します。ステータスコードが200〜399であれば成功とみなされます。
- TCP Socket: 指定したポートに対してTCP接続を試みます。接続が確立できれば成功とみなされます。
- Exec: コンテナ内で指定したコマンドを実行します。終了コードが0であれば成功とみなされます。
設定例
以下は、3つのProbeを組み合わせた設定例です。
apiVersion: v1
kind: Pod
metadata:
name: probe-demo
spec:
containers:
- name: my-app
image: my-app:v1
# 1. Startup Probe: 起動完了まで最大300秒 (10秒 * 30回) 待機
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
# 2. Readiness Probe: 起動後は5秒ごとにチェック。3回連続失敗でトラフィック遮断
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5 # Startup Probe完了後、さらに5秒待ってから開始
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
# 3. Liveness Probe: 起動後は10秒ごとにチェック。3回連続失敗で再起動
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 1
ベストプラクティス
1. Liveness ProbeとReadiness Probeを区別する
- Liveness: 「再起動すれば直る」致命的なエラーのみを検知するようにします。
- Readiness: 「今は忙しいが、待てば直る」一時的な不調や、起動処理中の状態を検知するようにします。
- アンチパターン: Liveness Probeでデータベースへの接続確認を行うこと。DBがダウンした際、全てのWebサーバーPodが同時に再起動を繰り返し(CrashLoopBackOff)、DB復旧後もシステム全体が復旧しなくなる恐れがあります(カスケード障害)。外部依存のチェックはReadiness Probeで行うか、あるいはProbeには含めずアプリのエラーハンドリングで対応すべきです。
2. Startup Probeを活用する
起動に時間がかかるアプリに対して、Liveness Probeの initialDelaySeconds を極端に長く設定するのは避けましょう。起動が早まった場合に無駄な待ち時間が発生したり、逆に起動が遅れた場合に誤って再起動されたりします。Startup Probeを使えば、起動完了を正確に検知し、その後即座にLiveness監視に移行できます。
3. タイムアウトと間隔の調整
timeoutSeconds(デフォルト1秒)は短すぎることがあります。アプリの負荷が高いときにタイムアウトで誤検知(False Positive)しないよう、少し余裕を持たせる(例: 2〜5秒)ことを検討してください。periodSeconds(デフォルト10秒)を短くしすぎると、Probe自体の負荷が無視できなくなります。
4. 専用のヘルスチェックエンドポイントを用意する
/ (ルート) へのアクセスをProbeにするのではなく、/healthz や /ready といった軽量な専用エンドポイントを実装することを推奨します。これにより、ログがアクセスログで埋め尽くされるのを防ぎ、チェック処理のオーバーヘッドを最小限に抑えられます。
5. Graceful Shutdownとの兼ね合い
Pod終了時(SIGTERM受信時)、Readiness Probeの状態に関わらず、KubernetesはEndpointsからPodを削除し始めます。しかし、反映にはタイムラグがあるため、アプリ側でも終了処理中に /ready エンドポイントが 503 を返すように実装しておくと、より安全にトラフィックを停止できます。